#include "login.h"
#include "StdFile.h"
#include "StdSqlite.h"
#include <dirent.h>
#include <sqlite3.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#define true 1
#define false 0
#define UserTableName "UserData"
#define FriendTableName "friends"
#define OnlineUser "OnlineUsers"

struct Client {
  int sock;
  char name[20];
};
typedef struct Client C;

struct Friend {
  char name[30];
};
typedef struct Friend F;

F *CreateFriend(const char *name) {
  F *f = (F *)malloc(sizeof(F));
  if (f == NULL) {
    printf("createFriedn malloc error\n");
    return NULL;
  }
  strcpy(f->name, name);
  return f;
}

void FreeFriend(F *f) {
  if (f != NULL) {
    free(f);
  }
}

int start(User *user1) {
  SQL *T = InitSqlite("./User_Account_data/USER.db");
  printf("#==================================#\n");
  printf("|1.注册||2.登录||3.删除账号||4.退出|\n");
  printf("#==================================#\n");
  int choice = 0;
  scanf("%d", &choice);
  while (getchar() != '\n')
    ;
  switch (choice) {
  case 1:
    Register(user1, T);

    break;
  case 2:
    int flag = Login(user1, T);
    while (flag == false) {
      flag = Login(user1, T);
    }
    break;
  case 3:
    DeleteAccount(T);
    start(user1);
    break;
  case 4:
    exit(0);
  default:
    printf("没有该选项\n");
    start(user1);
    break;
  }
  FreeSqlite(T);
}

int Register(User *user1, SQL *T) {

  printf("#==================================#\n");
  User user2 = {0, 0, 0};
  printf("请输入昵称:");
  scanf("%s", user2.Name);
  while (getchar() != '\n')
    ;
  
  printf("请输入账号:");
  scanf("%s", user2.account);
  while (getchar() != '\n')
    ;
  printf("请输入密码:");
  scanf("%s", user2.passwd);
  while (getchar() != '\n')
    ;
  char *UserName = NULL;
  UserName = GetTableData2(T, UserTableName, user2.account);
  if (UserName == NULL) {
    char *value[] = {user2.account, user2.passwd, user2.Name};
    InsertData(T, UserTableName, value, sizeof(value) / sizeof(value[0]));
    printf("#==================================#\n");
    printf("注册成功!\n");

    CreateFriendTable(user2.Name);
    CreateChatRecordTable(user2.Name);
    CreateOfflineTable(user2.Name);
    MakeFileFolder(user2.Name);
    CreateGroupTable(user2.Name);
    sleep(1);
    system("clear");
    start(user1);
  } else {
    sleep(1);
    system("clear");
    printf("已经存在该账号!!\n");
    printf("请重新请输入\n");
    start(user1);
  }
}

int Login(User *user1, SQL *T) {
  system("clear");
  printf("#==================================#\n");
  printf("请输入账号\n");
  scanf("%s", user1->account);
  printf("请输入密码\n");
  scanf("%s", user1->passwd);

  char *UserName =
      GetTableData(T, UserTableName, user1->account, user1->passwd);
  if (UserName == NULL) {
    printf("#==================================#\n");
    printf("账号或密码错误,请重新输入\n");
    printf("如忘记账号想重新注册请按0,重新输入请按1\n");
    int check;
    while (scanf("%d", &check)) {
      if (check == 1) {
        system("clear");
        return false;
      }
      if (check == 0) {
        Register(user1, T);
      } else {
        printf("没有这个选项!");
      }
    }
  } else {
    printf("登录成功\n\n");
    printf("======================\n");
    printf("|用户:%s,欢迎回来|\n", UserName);
    strcpy(user1->Name, UserName);
    sleep(1);
    system("clear");
    return true;
  }
  return 0;
}

void DeleteAccount(SQL *T) {
  char account[30];
  char passwd[30];
  printf("#==================================#\n");
  printf("请输入账号\n");
  scanf("%s", account);
  printf("请输入密码\n");
  scanf("%s", passwd);
  DeleteTableAccount(T, UserTableName, account, passwd);
}

void DisplayRegisterUser() {
  SQL *T = InitSqlite("./User_Account_data/USER.db");
  char **result;
  int row;
  int column;
  GetTableInfo(T, UserTableName, &result, &row, &column);

  for (int i = 1; i <= row; i++) {
    printf("昵称:%s,账号:%s", result[i * column + 2], result[i * column]);
    printf("\n");
  }
  sqlite3_free_table(result);
  FreeSqlite(T);
}

void CreateFriendTable(char *FromName) {
  SQL *T = InitSqlite("./Friend/Friend.db");
  char *tableName = (char *)malloc(strlen(FromName));
  strcpy(tableName, FromName);
  char *prolist[] = {"FriendName", "text"};
  CreateTable(T, tableName, prolist, sizeof(prolist) / sizeof(prolist[0]) / 2);
  free(tableName);
  FreeSqlite(T);
}

int MatchFriend(char *FromName, char *Toname) {
  SQL *T = InitSqlite("./Friend/Friend.db");
  char **result;
  int row, column;
  GetTableInfo(T, FromName, &result, &row, &column);
  for (int i = 1; i <= row; i++) {
    if (strcmp(Toname, result[i]) == 0)
      return false; // 存在则返回false
  }
  return true; // 不存在则返回true
  FreeSqlite(T);
}

void InsertFriendData(char *FromName, char *ToName) {
  SQL *T = InitSqlite("./Friend/Friend.db");
  char *myself = (char *)malloc(strlen(FromName) + 3);
  strcpy(myself, FromName);
  char *friend = (char *)malloc(strlen(ToName) + 3);
  strcpy(friend, ToName);

  char *value1[] = {friend};
  char *value2[] = {myself};

  int flag = MatchFriend(FromName, ToName);
  if (flag == true) {
    InsertData(T, myself, value1, sizeof(value1) / sizeof(value1[0]));
    InsertData(T, friend, value2, sizeof(value2) / sizeof(value2[0]));
    printf("===============\n");
    printf("您跟[%s]成为好友\n", FromName);
  } else {
    printf("==============================\n");
    printf("该用户已经是好友了,不能反复添加\n");
  }
  // 释放动态分配的内存
  free(myself);
  free(friend);
  FreeSqlite(T);
}

void DisplayFriends(char *FromName) {
  SQL *T = InitSqlite("./Friend/Friend.db");
  char **result;
  int row;
  int column;
  GetTableInfo(T, FromName, &result, &row, &column);
  for (int i = 1; i <= row; i++) {
    printf("========\n");
    printf("好友%s\n", result[i]);
  }
  sqlite3_free_table(result);
  FreeSqlite(T);
}

DLlist *GetFriendsData(char *FromName) {
  DLlist *list = (DLlist *)malloc(sizeof(DLlist));
  InitDLlist(list);
  SQL *s = InitSqlite("./Friend/Friend.db");
  char **result;
  int row;
  int column;
  GetTableInfo(s, FromName, &result, &row, &column);
  for (int i = 1; i <= row; i++) {
    InsertTail(list, CreateFriend(result[i]));
  }

  sqlite3_free_table(result);
  FreeSqlite(s);
  return list;
}

void DisplayOnlineFriends(char *FromName) {
  SQL *s1 = InitSqlite("./User_Account_data/USER.db");
  SQL *s2 = InitSqlite("./Friend/Friend.db");
  char **result1;
  char **result2;
  int row1;
  int row2;
  int column1;
  int column2; // 好友
  GetTableInfo(s1, OnlineUser, &result1, &row1, &column1);
  GetTableInfo(s2, FromName, &result2, &row2, &column2);
  char **result3 = (char **)malloc(row1 * sizeof(char *)); // 为result3分配内存
  for (int i = 0; i < row1; i++) {
    result3[i] = (char *)malloc(31 * sizeof(char));
  }
  int k = 0;
  for (int i = 1; i <= row1; i++) {              // 修正遍历的方式
    for (int j = 1; j <= row2; j++) {            // 修正遍历的方式
      if (strcmp(result1[i], result2[j]) == 0) { // 使用strcmp函数进行字符串比较
        strcpy(result3[k], result1[i]);
        k++;
      }
    }
  }
  if (k == 0) {
    printf("============\n");
    printf("没有好友在线\n");
  } else {
    for (int i = 0; i < k; i++) {
      printf("==========\n");
      printf("好友%s在线\n", result3[i]);
    }
  }
  // 释放result3数组的内存
  for (int i = 0; i < row1; i++) {
    free(result3[i]);
  }
  free(result3);
  sqlite3_free_table(result1);
  sqlite3_free_table(result2);
  FreeSqlite(s1);
  FreeSqlite(s2);
}

void deleteFriends(char *fromName, char *toName) {
  SQL *T = InitSqlite("./Friend/Friend.db");
  char where[100] = {0};
  sprintf(where, "FriendName = '%s'", toName);
  DeleteData(T, fromName, where);
  sprintf(where, "FriendName = '%s'", fromName);
  DeleteData(T, toName, where);
  FreeSqlite(T);
}

void CreateChatRecordTable(char *FromName) {
  SQL *T = InitSqlite("./ChatRecord/Record.db");
  char *tableName = (char *)malloc(strlen(FromName));
  strcpy(tableName, FromName);
  char *prolist[] = {"FromName", "text", "content", "text", "ToName", "text"};
  CreateTable(T, tableName, prolist, sizeof(prolist) / sizeof(prolist[0]) / 2);
  free(tableName);
  FreeSqlite(T);
}

void ChatRecordSaved(char *FromName, char *content, char *ToName) {
  SQL *T = InitSqlite("./ChatRecord/Record.db");
  char *values[] = {FromName, content, ToName};
  InsertData(T, FromName, values, sizeof(values) / sizeof(values[0]));
  InsertData(T, ToName, values, sizeof(values) / sizeof(values[0]));
  FreeSqlite(T);
}

void DisplayCharRecord(char *fromName) {
  SQL *T = InitSqlite("./ChatRecord/Record.db");
  char **result;
  int row;
  int column;
  GetTableInfo(T, fromName, &result, &row, &column);
  for (int i = 1; i <= row; i++) {
    printf("=========================================\n");
    printf("发送用户:%s 内容:%s 接受用户:%s\n", result[i * column],
           result[i * column + 1], result[i * column + 2]);
  }
  sqlite3_free_table(result);
  FreeSqlite(T);
  sleep(2);
}

int IsUserExit(char *name) {
  SQL *T = InitSqlite("./User_Account_data/USER.db");
  char **result;
  int row;
  int column;
  GetTableInfo(T, UserTableName, &result, &row, &column);
  for (int i = 1; i <= row; i++) {
    if (strcmp(name, result[i * column + 2]) == 0) {
      return true;
    }
  }
  return false;
  sqlite3_free_table(result);
  FreeSqlite(T);
}

void InsertOnlineUser(char *FromName) {
  SQL *T = InitSqlite("./User_Account_data/USER.db");
  char *myself = (char *)malloc(strlen(FromName) + 3);
  strcpy(myself, FromName);
  char *value[] = {myself};
  InsertData(T, OnlineUser, value, sizeof(value) / sizeof(value[0]));

  free(myself);
  FreeSqlite(T);
}

void DisplayOnlineUser() {
  SQL *T = InitSqlite("./User_Account_data/USER.db");
  char **result;
  int row;
  int column;
  GetTableInfo(T, OnlineUser, &result, &row, &column);

  for (int i = 1; i <= row; i++) {
    printf("================\n");
    printf("用户:%s在线\n", result[i]);
  }
  sqlite3_free_table(result);
  FreeSqlite(T);
}

void DeleteOnlineUser(char *FromName) {
  SQL *T = InitSqlite("./User_Account_data/USER.db");
  DeleteOnlineData(T, OnlineUser, FromName);
  FreeSqlite(T);
}

void MakeGroupFolder(char *name) { MakeDir2(name); }

void CreateGroupTable(char *name) {
  SQL *T = InitSqlite("./Group/user.db");
  char *prolist[] = {"加入的群", "text"};
  if (CheckTableExists(T, name) == 0) {
    CreateTable(T, name, prolist, sizeof(prolist) / sizeof(prolist[0]) / 2);
  }
  FreeSqlite(T);
}

void CreateGroup(char *fromName, char *name1) {
  char name[100] = {0};
  strcpy(name, name1);
  while (getchar() != '\n')
    ;
  SQL *T1 = InitSqlite("./Group/Group.db");
  SQL *T2 = InitSqlite("./Group/GroupChat.db");
  SQL *T3 = InitSqlite("./Group/user.db");
  char *prolist1[] = {"群人员", "text"};
  char *prolist2[] = {"FromName", "text", "content", "text"};
  char *prolist3[] = {"加入的群", "text"};

  if (CheckTableExists(T1, name) == 0) {
    CreateTable(T1, name, prolist1, sizeof(prolist1) / sizeof(prolist1[0]) / 2);
  }
  if (CheckTableExists(T2, name) == 0) {
    CreateTable(T2, name, prolist2, sizeof(prolist2) / sizeof(prolist2[0]) / 2);
  }
  if (CheckTableExists(T3, fromName) == 0) {
    CreateTable(T3, fromName, prolist3,
                sizeof(prolist3) / sizeof(prolist3[0]) / 2);
  }
  FreeSqlite(T1);
  FreeSqlite(T2);
  FreeSqlite(T3);
}

void PullGroup2(char *fromName, char *groupName) {
  SQL *T1 = InitSqlite("./Group/Group.db");
  SQL *T2 = InitSqlite("./Group/user.db");
  char *fromName1 = (char *)malloc(strlen(fromName) + 2);
  char *groupName1 = (char *)malloc(strlen(groupName) + 2);
  strcpy(fromName1, fromName);
  strcpy(groupName1, groupName);
  char *value1[] = {fromName1};
  char *value3[] = {groupName1};
  if (MatchGroup(fromName1, groupName1) == true) {
    InsertData(T1, groupName1, value1, sizeof(value1) / sizeof(value1[0]));
  }
  if (Matchuser(fromName1, groupName1) == true) {
    InsertData(T2, fromName1, value3, sizeof(value3) / sizeof(value3[0]));
  }
  free(fromName1);
  free(groupName1);
  FreeSqlite(T1);
  FreeSqlite(T2);
}

void PullGroup(char *fromName, char *ToName, char *groupName) {
  SQL *T1 = InitSqlite("./Group/Group.db");
  SQL *T2 = InitSqlite("./Group/user.db");

  char *fromName1 = (char *)malloc(strlen(fromName) + 2);
  char *toName1 = (char *)malloc(strlen(ToName) + 2);
  char *groupName1 = (char *)malloc(strlen(groupName) + 2);

  strcpy(fromName1, fromName);
  strcpy(toName1, ToName);
  strcpy(groupName1, groupName);
  char *value1[] = {fromName1};
  char *value2[] = {toName1};
  char *value3[] = {groupName1};

  if (MatchGroup(fromName1, groupName1) == true) {
    InsertData(T1, groupName1, value1, sizeof(value1) / sizeof(value1[0]));
  }
  if (MatchGroup(toName1, groupName1) == true) {
    InsertData(T1, groupName1, value2, sizeof(value2) / sizeof(value2[0]));
  }

  if (Matchuser(fromName1, groupName1) == true) {
    InsertData(T2, fromName1, value3, sizeof(value3) / sizeof(value3[0]));
  }
  if (Matchuser(toName1, groupName1) == true) {
    InsertData(T2, toName1, value3, sizeof(value3) / sizeof(value3[0]));
  }
  free(fromName1);
  free(toName1);
  free(groupName1);
  FreeSqlite(T1);
  FreeSqlite(T2);
}

int CheckGroupExit(char *TableName) {
  SQL *T = InitSqlite("./Group/Group.db");
  if (CheckTableExists(T, TableName) == 1) {
    return true; // 表格存在
  } else {
    return false; // 表格不存在
  }
  FreeSqlite(T);
  return 0;
}

int MatchGroup(char *Name, char *groupName) {
  SQL *T = InitSqlite("./Group/Group.db");
  char **result;
  int row;
  int column;
  GetTableInfo(T, groupName, &result, &row, &column);
  for (int i = 1; i <= row; i++) {
    if (strcmp(Name, result[i]) == 0) {
      return false; // 群存在则返回false
    }
  }
  return true; // 不存在则返回true
  sqlite3_free_table(result);
  FreeSqlite(T);
}

int Matchuser(char *name, char *groupName) {

  SQL *T = InitSqlite("./Group/user.db");
  char **result;
  int row;
  int column;
  GetTableInfo(T, name, &result, &row, &column);
  for (int i = 1; i <= row; i++) {
    if (strcmp(groupName, result[i]) == 0) {
      return false; // 存在返回false
    }
  }
  return true; // 不存在返回true
  sqlite3_free_table(result);
  FreeSqlite(T);
}

DLlist *GetGroupMembers(char *groupName) {
  DLlist *list = (DLlist *)malloc(sizeof(DLlist));
  InitDLlist(list);
  SQL *T = InitSqlite("./Group/Group.db");
  char **result;
  int row;
  int column;
  GetTableInfo(T, groupName, &result, &row, &column);
  for (int i = 1; i <= row; i++) {
    InsertTail(list, CreateFriend(result[i]));
  }
  sqlite3_free_table(result);
  FreeSqlite(T);
  return list;
}

DLlist *FindGroupIntersection(DLlist *list1, DLlist *list2) {
  struct Node *tra1 = list1->head;
  struct Node *tra2 = list2->head;
  DLlist *list3 = (DLlist *)malloc(sizeof(DLlist));
  if (list3 == NULL) {
    printf("FindIntersection malloc error\n");
  }
  InitDLlist(list3);

  while (tra1 != NULL) {
    C *c = (C *)tra1->data;
    tra2 = list2->head;
    while (tra2 != NULL) {
      F *f = (F *)tra2->data;
      if (strcmp(c->name, f->name) == 0) // 字符串匹配
      {
        struct Node *tra3 = list3->head;
        int flag = 0;

        while (tra3 != NULL) {
          if (tra3->data == tra1->data) {
            flag = 1;
          }
          tra3 = tra3->next;
        }
        if (flag == 0) {
          InsertTail(list3, tra1->data);
        }
      }
      tra2 = tra2->next;
    }
    tra1 = tra1->next;
  }
  return list3;
}

void insertGroupChat(char *fromName, char *content, char *groupName) {
  SQL *T = InitSqlite("./Group/GroupChat.db");
  char *value[] = {fromName, content};
  InsertData(T, groupName, value, sizeof(value) / sizeof(value[0]));

  FreeSqlite(T);
}

int IsOnline(char *name) {
  SQL *T = InitSqlite("./User_Account_data/USER.db");
  char **result;
  int row;
  int column;
  GetTableInfo(T, OnlineUser, &result, &row, &column);
  for (int i = 1; i <= row; i++) {
    if (strcmp(name, result[i]) == 0) {

      return true; // true为在线
    }
  }
  return false; // false为离线
  sqlite3_free_table(result);
  FreeSqlite(T);
}

void CreateOfflineTable(char *FromName) {
  SQL *T = InitSqlite("./OfflineLibrary/offline.db");
  char *tableName = (char *)malloc(strlen(FromName));
  strcpy(tableName, FromName);
  char *prolist[] = {"发消息的人", "text", "内容", "text"};
  CreateTable(T, tableName, prolist, sizeof(prolist) / sizeof(prolist[0]) / 2);
  free(tableName);
  FreeSqlite(T);
}

void insertOfflineChat(char *FromName, char *content, char *ToName) {
  SQL *T = InitSqlite("./OfflineLibrary/offline.db");
  char *value[] = {FromName, content};
  InsertData(T, ToName, value, sizeof(value) / sizeof(value[0]));
  FreeSqlite(T);
}

void DisplayOfflineChat(char *name) {
  SQL *T = InitSqlite("./OfflineLibrary/offline.db");
  char **result;
  int row;
  int column;
  GetTableInfo(T, name, &result, &row, &column);
  for (int i = 1; i <= row; i++) {
    printf("用户%s发送的内容为:%s\n", result[i * column],
           result[i * column + 1]);
  }
  sqlite3_free_table(result);
  FreeSqlite(T);
}

void deleteOfflineChat(char *name) {
  SQL *T = InitSqlite("./OfflineLibrary/offline.db");
  ClearDataTable(T, name);
  FreeSqlite(T);
}

void MakeFileFolder(char *name) { MakeDir1(name); }

int IfFolderExit(char *name, char *FromName) {

  char account[100] = {0};
  strcpy(account, name);

  char temp[200] = "./";
  strcat(temp, "FileLibrary");
  strcat(temp, "/");
  strcat(temp, FromName);

  const char *folderPath = temp;
  const char *fileName = account;

  // 打开文件夹
  DIR *folder = opendir(folderPath);
  if (folder == NULL) {
    printf("===========\n");
    printf("文件夹不存在\n");
    return 0;
  }

  // 遍历文件夹中的文件
  struct dirent *entry;
  int fileExists = 0;
  while ((entry = readdir(folder)) != NULL) {
    if (strcmp(entry->d_name, fileName) == 0) {
      // 找到指定的文件
      fileExists = 1;
      break;
    }
  }

  // 关闭文件夹
  closedir(folder);

  if (fileExists == 1) {
    return true;
  } else {
    return false;
  }
}

int IfFolderExit2(char *name, char *FromName) {

  char account[100] = {0};
  strcpy(account, name);

  char temp[200] = "./";
  strcat(temp, "Group");
  strcat(temp, "/");
  strcat(temp, "GroupFile");
  strcat(temp, "/");
  strcat(temp, FromName);
  const char *folderPath = temp;
  const char *fileName = account;

  DIR *folder = opendir(folderPath);
  if (folder == NULL) {
    printf("============\n");
    printf("文件夹不存在\n");
    return 0;
  }

  // 遍历文件夹中的文件
  struct dirent *entry;
  int fileExists = 0;

  while ((entry = readdir(folder)) != NULL) {
    if (strcmp(entry->d_name, fileName) == 0) {
      // 找到指定的文件
      fileExists = 1;
      break;
    }
  }

  // 关闭文件夹
  closedir(folder);

  if (fileExists == 1) {
    return true;
  } else {
    return false;
  }
}